<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" >

<title>TinyMCE 编辑邮件模板 FineUICore | 没想好的个人博客</title>

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">

<!-- <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous"> -->
   <!-- Font Awesome CSS-->
   <link href="https://cdn.bootcss.com/font-awesome/5.13.0/css/all.css" rel="stylesheet">

   <link rel="stylesheet" href="https://cdn.bootcss.com/font-awesome/5.7.2/css/all.min.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">

<link rel="shortcut icon" href="https://shixixiyue.gitee.io//favicon.ico?v=1709791195950">
<link rel="stylesheet" href="https://shixixiyue.gitee.io//styles/main.css">



<link rel="stylesheet" href="https://unpkg.com/aos@next/dist/aos.css" />
<script src="https://jsd.onmicrosoft.cn/npm/vue/dist/vue.js"></script>


<style>
  .hljs-ln{
    padding-bottom: 1.2rem;
    margin: 0rem !important;
  }
  .hljs-ln td {
    border: none !important;
    padding: 2px 6px !important;
    line-height: 1.2rem;
    font-size: 1rem;
  }
  .hljs-ln tr td:first-child  {
    color: cadetblue;
    border-right: 1px solid !important;
  }
  .hljs-ln tr {
    border: none !important;
  }
</style>

    <meta name="description" content="
昨天设计发送邮件，需要设计邮件模板，将动态的字段放入模板里，使用了TinyMCE今天来分享一下；

测试环境：
FineUICore 8.1 （前端的应该不区别FineUI版本）
TinyMCE版本 5.10.0 （下面会写升级方法）

..." />
    <meta name="keywords" content="FineUICore" />
  </head>
  <body>
    <div id="app" class="main">

      <div class="sidebar" :class="{ 'full-height': menuVisible }">
  <div class="top-container" data-aos="fade-right">
    <div class="top-header-container">
      <a class="site-title-container" href="https://shixixiyue.gitee.io/">
        <img src="https://shixixiyue.gitee.io//images/avatar.png?v=1709791195950" class="site-logo">
        <h1 class="site-title">没想好的个人博客</h1>
      </a>
      <div class="menu-btn" @click="menuVisible = !menuVisible">
        <div class="line"></div>
      </div>
    </div>
    <div>
      
        
          <a href="https://shixixiyue.gitee.io/" class="site-nav">
            首页
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/4gOKry8Qv/" class="site-nav">
            .Net Core
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/njETBpqXu/" class="site-nav">
            FineUICore
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/XyXyeLOBB" class="site-nav">
            读书笔记
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/TyVX6hfCJ" class="site-nav">
            Vue笔记
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/3Hz2sPtzO/" class="site-nav">
            产品
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tag/Db1wShB_E" class="site-nav">
            其他
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io/" class="site-nav">
            一一一一一一一一一
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//archives" class="site-nav">
            文章归档
          </a>
        
      
        
          <a href="https://shixixiyue.gitee.io//tags" class="site-nav">
            全部标签
          </a>
        
      
    </div>
  </div>
  <div class="bottom-container" data-aos="flip-up" data-aos-offset="0">
    <div class="social-container">
      
        
      
        
      
        
      
        
      
        
      
    </div>
    <div class="site-description">
      没事啥都说
    </div>
    <div class="site-footer">
      QQ：<a href="tencent://message/?uin=935732994&Site=''&Menu=yes">935732994<a/> <a href="http://beian.miit.gov.cn">京ICP备2024045283号<a/> | <a class="rss" href="https://shixixiyue.gitee.io//atom.xml" target="_blank">RSS</a>
    </div>
  </div>
</div>


      <div class="main-container">
        <div class="content-container" data-aos="fade-up">
          <div class="post-detail">
            <h2 class="post-title">TinyMCE 编辑邮件模板 FineUICore</h2>
            <div class="post-date">2022-09-01
            
                
                  <a href="https://shixixiyue.gitee.io/tag/njETBpqXu/" class="tag">
                    FineUICore
                  </a>
                
            </div>
            
              <div class="feature-container" style="background-image: url('https://shixixiyue.gitee.io//post-images/tinymce-bian-ji-you-jian-mo-ban-fineuicore.gif')">
              </div>
            
            <div class="post-content" v-pre>
              <blockquote>
<p>昨天设计发送邮件，需要设计邮件模板，将动态的字段放入模板里，使用了TinyMCE今天来分享一下；</p>
</blockquote>
<p>测试环境：<br>
FineUICore 8.1 （前端的应该不区别FineUI版本）<br>
TinyMCE版本 5.10.0 （下面会写升级方法）</p>
<!-- more -->
<p><ul class="markdownIt-TOC">
<li>
<ul>
<li>
<ul>
<li>
<ul>
<li><a href="#1-%E5%8D%87%E7%BA%A7tinymce">1. 升级TinyMCE</a></li>
<li><a href="#2-tinymce%E7%9A%84%E5%8F%82%E6%95%B0">2. TinyMCE的参数</a></li>
<li><a href="#3-tinymce%E7%9A%84%E6%8F%92%E4%BB%B6">3. TinyMCE的插件</a></li>
<li><a href="#4-%E6%A0%B8%E5%BF%83%E5%AE%9E%E7%8E%B0-%E5%BD%93%E7%84%B6%E6%98%AFjs">4. 核心实现 当然是JS</a></li>
<li><a href="#5-%E5%90%8E%E5%8F%B0">5. 后台</a></li>
<li><a href="#6-%E6%BA%90%E7%A0%81">6. 源码</a></li>
<li><a href="#%E5%90%8E%E8%AE%B0%E5%92%8C%E9%97%AE%E9%A2%98">后记和问题</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</p>
<p>先上图</p>
<figure data-type="image" tabindex="1"><img src="https://shixixiyue.gitee.io//post-images/1684483828622.gif" alt="插入" loading="lazy"></figure>
<h4 id="1-升级tinymce">1. 升级TinyMCE</h4>
<p>FineUI自带的好像是4.X，升级我之前发过帖子，需要下载最新的包，覆盖就行了（\wwwroot\res\third-party\tinymce\）</p>
<p>不升级的话会有BUG，插入的字段会跑偏；<br>
升级之后的话会有BUG，高度不会自适应，需要指定高度，这个倒是无所谓，等我修复了再放出来；</p>
<h4 id="2-tinymce的参数">2. TinyMCE的参数</h4>
<p>TinyMCE的参数通过 .Options( 去设置，参考 http://tinymce.ax-z.cn/ 就可以了，<br>
比如设置中文</p>
<pre><code>F.OptionItem().Key(&quot;language&quot;).Value(&quot;zh_CN&quot;).PersistOriginal(false),
</code></pre>
<p>PersistOriginal 表示是否原样输出，如果为false会当作字符串，比如输出 false ，就为true就好了，</p>
<p>完整配置和注释如下</p>
<pre><code>.Options(
    //语言
    F.OptionItem().Key(&quot;language&quot;).Value(&quot;zh_CN&quot;).PersistOriginal(false),
    //自定义css路径
    F.OptionItem().Key(&quot;content_css&quot;).Value(Url.Content(&quot;~/res/css/FineUIOvereide.css&quot;)).PersistOriginal(false),
    //不要上面的菜单
    F.OptionItem().Key(&quot;menubar&quot;).Value(&quot;false&quot;).PersistOriginal(true),
    //最小高度
    F.OptionItem().Key(&quot;min_height&quot;).Value(&quot;500&quot;).PersistOriginal(true),
    //插件选择
    F.OptionItem().Key(&quot;plugins&quot;).Value(&quot;['link','code','textcolor colorpicker ','noneditable importcss autoresize']&quot;).PersistOriginal(true),
    //工具条
    F.OptionItem().Key(&quot;toolbar1&quot;).Value(&quot;bold italic underline strikethrough | numlist bullist | alignleft aligncenter alignright | link unlink | code&quot;),
    //作为标签的class类
    F.OptionItem().Key(&quot;noneditable_noneditable_class&quot;).Value(&quot;tag&quot;).PersistOriginal(false)
)
</code></pre>
<h4 id="3-tinymce的插件">3. TinyMCE的插件</h4>
<p>要实现标签功能，需要用到 两个插件 <a href="http://tinymce.ax-z.cn/plugins/noneditable.php">noneditable不可编辑插件</a>  和 <a href="http://tinymce.ax-z.cn/plugins/importcss.php">importcss引用css插件</a>，放到plugins 最后就行了；这里我设置了 noneditable_noneditable_class ，就是这个css 将作为 不可编辑的标记；</p>
<p>如果没升级 TinyMCE 出现以下情况</p>
<figure data-type="image" tabindex="2"><img src="https://shixixiyue.gitee.io//post-images/1684483838739.gif" alt="插入" loading="lazy"></figure>
<p>插入焦点会很奇怪；</p>
<h4 id="4-核心实现-当然是js">4. 核心实现 当然是JS</h4>
<p>直接上代码，看注释</p>
<pre><code>//一个字段的合集 [{id,value},{id,value}]
const fields = @Html.Raw(ViewBag.myFields);

F.ready(function () {
    fields.forEach(item =&gt; {
        //Label 
        let tag = new F.Label({
            cls: &quot;tag&quot;,
            hideLabel: true,
            value: item.value,
            renderTo: F.ui.field.bodyEl,
        });
        //点击事件
        tag.el.on(&quot;click&quot;, () =&gt; {
            //拼一个标签 把值塞进去
            let span = `&lt;span class=&quot;tag&quot; id=&quot;${item.id}&quot; style=&quot;height:20px;line-height:20px;margin:0px 5px;&quot;&gt;${item.value}&lt;/span&gt;`;
            //注意获取编辑控件的用法
            F.ui.HtmlEditor1.getEditorInstance().insertContent(span);
        });
    })
});
</code></pre>
<p>tag 是我自己写的样式，不放出来了，30RMB</p>
<p>到这就能插入了；</p>
<h4 id="5-后台">5. 后台</h4>
<p>后台需要保存，发送邮件时需要替换标签，这里用的正则替换，也放出来</p>
<pre><code>myFields.ForEach(item =&gt;
{
    var v = &quot;&quot;;
    //如果有数据
    if (data.ContainsKey(item.id))
    {
        v = data[item.id].ToString();
    }
    //正则替换模板
    var regEx_style = $&quot;&lt;span[^&gt;]*id=\&quot;{item.id}\&quot;[^&gt;]*?&gt;[\\s\\S]*?&lt;\\/span&gt;&quot;;
    temp = Regex.Replace(temp, regEx_style, v);
});
</code></pre>
<p>这里的span 要和前台的 span标签一致，否则找不到，属于约定，也可以用一个参数控制；</p>
<h4 id="6-源码">6. 源码</h4>
<p>6.1 前台代码</p>
<pre><code>@{
    ViewBag.Title = &quot;没想好&quot;;
    var F = Html.F();
}

@section head {
}

@section body {
    @(
    F.Panel().NoBorderAndHeader().Layout(LayoutType.HBox).IsViewPort(true)
    .Items(
        F.Panel().ID(&quot;field&quot;).BoxFlex(1).Title(&quot;字段&quot;).Toolbars(F.Toolbar().Items(
            F.Button().Text(&quot;测试&quot;).OnClick(Url.Action(&quot;test&quot;), new Parameter(&quot;temp&quot;, &quot;F.ui.HtmlEditor1.getValue()&quot;))
            )),
        F.HtmlEditor().BoxFlex(3).ID(&quot;HtmlEditor1&quot;).Editor(Editor.TinyMCE).LabelAlign(LabelAlign.Top)
                .BasePath(Url.Content(&quot;~/res/third-party/tinymce/&quot;)).ToolbarSet(EditorToolbarSet.Full)
                //.Height(600)
                .Options(
                    F.OptionItem().Key(&quot;language&quot;).Value(&quot;zh_CN&quot;).PersistOriginal(false),
                    F.OptionItem().Key(&quot;content_css&quot;).Value(Url.Content(&quot;~/res/css/FineUIOvereide.css&quot;)).PersistOriginal(false),
                    F.OptionItem().Key(&quot;menubar&quot;).Value(&quot;false&quot;).PersistOriginal(true),
                    F.OptionItem().Key(&quot;min_height&quot;).Value(&quot;500&quot;).PersistOriginal(true),
                    F.OptionItem().Key(&quot;plugins&quot;).Value(&quot;['link','code','textcolor colorpicker ','noneditable importcss autoresize']&quot;).PersistOriginal(true),
                    F.OptionItem().Key(&quot;toolbar1&quot;).Value(&quot;bold italic underline strikethrough | numlist bullist | alignleft aligncenter alignright | link unlink | code&quot;),
                    F.OptionItem().Key(&quot;noneditable_noneditable_class&quot;).Value(&quot;tag&quot;).PersistOriginal(false)
                )
        )
  )
}

@section script {
    &lt;script&gt;
        const fields = @Html.Raw(ViewBag.myFields);
        F.ready(function () {
            fields.forEach(item =&gt; {
                let tag = new F.Label({
                    cls: &quot;tag&quot;,
                    hideLabel: true,
                    value: item.value,
                    renderTo: F.ui.field.bodyEl,
                });
                
                tag.el.on(&quot;click&quot;, () =&gt; {
                    let span = `&lt;span class=&quot;tag&quot; id=&quot;${item.id}&quot; style=&quot;height:20px;line-height:20px;margin:0px 5px;&quot;&gt;${item.value}&lt;/span&gt;`;
                    F.ui.HtmlEditor1.getEditorInstance().insertContent(span);
                });
            })
        });
    &lt;/script&gt;
}
</code></pre>
<p>6.2 后台代码</p>
<pre><code>using FineUICore.EmptyProject.Controllers;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace FineUICoreEx.Demo.Areas.Other.Controllers
{
    [Area(&quot;Other&quot;)]
    public class TinyMCETestController : BaseController
    {
        public IActionResult Index()
        {
            List&lt;myField&gt; myFields = GetmyFields();
            ViewBag.myFields = JArray.FromObject(myFields).ToString(Formatting.None);
            return View();
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task&lt;IActionResult&gt; test(string temp)
        {
            JObject data = new JObject();
            GetData().ForEach(item =&gt;
            {
                data.Add(item.id, item.value);
            });
            List&lt;myField&gt; myFields = GetmyFields();
            myFields.ForEach(item =&gt;
            {
                var v = &quot;&quot;;
                if (data.ContainsKey(item.id))
                {
                    v = data[item.id].ToString();
                }
                var regEx_style = $&quot;&lt;span[^&gt;]*id=\&quot;{item.id}\&quot;[^&gt;]*?&gt;[\\s\\S]*?&lt;\\/span&gt;&quot;;
                temp = Regex.Replace(temp, regEx_style, v);
            });

            ShowAlert(temp);
            return FineUICore.UIHelper.Result();
        }

        private List&lt;myField&gt; GetData()
        {
            return new List&lt;myField&gt;() {
                new myField() { id =&quot;date&quot;,value=DateTime.Now.ToString(&quot;yyyy-MM-dd&quot;) },
                new myField() { id =&quot;name&quot;,value=&quot;我不是标题&quot; },
                new myField() { id =&quot;content&quot;,value=&quot;内容22223423&lt;br/&gt;内容22223423&quot; },
            };
        }

        public dynamic GetmyFields()
        {
            return new List&lt;myField&gt;() {
                new myField() { id =&quot;date&quot;,value=&quot;日期&quot; },
                new myField() { id =&quot;name&quot;,value=&quot;姓名&quot; },
                new myField() { id =&quot;title&quot;,value=&quot;标题&quot; },
                new myField() { id =&quot;content&quot;,value=&quot;内容&quot; },
            };
        }
    }

    public class myField
    {
        public string id { get; set; }
        public string value { get; set; }
    }
}

</code></pre>
<p>引用图</p>
<figure data-type="image" tabindex="3"><img src="https://shixixiyue.gitee.io//post-images/1684483854701.png" alt="实际图" loading="lazy"></figure>
<hr>
<h4 id="后记和问题">后记和问题</h4>
<ul>
<li>问题1</li>
</ul>
<p>目前遇到的问题是<br>
F.ui.HtmlEditor2.getEditorInstance() 页面初始时会获取不到，需要延迟</p>
<ul>
<li>问题2</li>
</ul>
<p>另外页面初始时回发，会有一个</p>
<pre><code>n.beforeAjax(function () {
    t.oIlO0.initialized &amp;&amp; t.oIlO0.save()
})
</code></pre>
<p>这个会报错，不要回发或者延迟回发就好了 <code>绝对是BUG</code></p>
<ul>
<li>代码断</li>
</ul>
<pre><code>let Editor = F.ui.HtmlEditor1.getEditorInstance();
Editor.on('focus', function () {
    ...
});
Editor.on('change', ...);
</code></pre>
<pre><code>F.HtmlEditor().ID(&quot;HtmlEditor1&quot;).Editor(Editor.TinyMCE)
 .Label(&quot;标题&quot;)
 .LabelAlign(LabelAlign.Top)
 .BasePath(Url.Content(&quot;~/res/third-party/tinymce/&quot;))
 .ToolbarSet(EditorToolbarSet.Full)//好像影响menubar:false
 .Options(
    F.OptionItem().Key(&quot;language&quot;).Value(&quot;zh_CN&quot;).PersistOriginal(false),
    F.OptionItem().Key(&quot;toolbar&quot;).Value(&quot;false&quot;).PersistOriginal(true),//没工具条
    F.OptionItem().Key(&quot;menubar&quot;).Value(&quot;false&quot;).PersistOriginal(true),//没菜单
    F.OptionItem().Key(&quot;statusbar&quot;).Value(&quot;false&quot;).PersistOriginal(true),//没状态栏
    F.OptionItem().Key(&quot;height&quot;).Value(&quot;58&quot;).PersistOriginal(true),
    F.OptionItem().Key(&quot;content_css&quot;).Value(Url.Content(&quot;~/res/css/FineUIOvereide.css&quot;)).PersistOriginal(false), 
    F.OptionItem().Key(&quot;plugins&quot;)
    .Value(&quot;['noneditable importcss']&quot;).PersistOriginal(true),
    F.OptionItem().Key(&quot;noneditable_noneditable_class&quot;).Value(&quot;tag&quot;).PersistOriginal(false)
    ),
F.HtmlEditor().ID(&quot;HtmlEditor2&quot;).Editor(Editor.TinyMCE)
 .Label(&quot;内容&quot;)
 .LabelAlign(LabelAlign.Top)
 .BasePath(Url.Content(&quot;~/res/third-party/tinymce/&quot;))
 .Options(
    F.OptionItem().Key(&quot;language&quot;).Value(&quot;zh_CN&quot;).PersistOriginal(false),
    F.OptionItem().Key(&quot;plugins&quot;)
    .Value(&quot;['link','code','textcolor colorpicker ','noneditable importcss  autoresize preview']&quot;).PersistOriginal(true),//插件
    F.OptionItem().Key(&quot;min_height&quot;).Value(&quot;350&quot;).PersistOriginal(true),//最小高度
    F.OptionItem().Key(&quot;toolbar1&quot;)
      .Value(&quot;fontselect fontsizeselect | bold italic underline strikethrough | numlist bullist | alignleft aligncenter alignright | link unlink | code preview wordcount&quot;),//工具栏
    F.OptionItem().Key(&quot;noneditable_noneditable_class&quot;).Value(&quot;tag&quot;).PersistOriginal(false),
    F.OptionItem().Key(&quot;content_css&quot;).Value(Url.Content(&quot;~/res/css/FineUIOvereide.css&quot;)).PersistOriginal(false),//引用css
    F.OptionItem().Key(&quot;menubar&quot;).Value(&quot;false&quot;).PersistOriginal(true),//没有菜单
    F.OptionItem().Key(&quot;branding&quot;).Value(&quot;false&quot;).PersistOriginal(true),//没有logo
    F.OptionItem().Key(&quot;font_formats&quot;).Value(&quot;微软雅黑=Microsoft YaHei,Helvetica Neue,PingFang SC,sans-serif;苹果苹方=PingFang SC,Microsoft YaHei,sans-serif;宋体=simsun,serif&quot;).PersistOriginal(false)//字体
    )
</code></pre>

            </div>
            
              <div class="tag-container">
                
                  <a href="https://shixixiyue.gitee.io/tag/njETBpqXu/" class="tag">
                    FineUICore
                  </a>
                
              </div>
            
            
              <div class="next-post">
                <div class="next">下一篇</div>
                <a href="https://shixixiyue.gitee.io/dai-ma-duan-yi/">
                  <h3 class="post-title">
                    代码段（一）
                  </h3>
                </a>
              </div>
            

            

          </div>

        </div>
      </div>
    </div>

    <script src="https://unpkg.com/aos@next/dist/aos.js"></script>
<script type="application/javascript">

AOS.init();

var app = new Vue({
  el: '#app',
  data: {
    menuVisible: false,
  },
})

</script>


  <script src="//jsd.onmicrosoft.cn/gh/highlightjs/cdn-release@11.5.1/build/highlight.min.js"></script>
  <script>
    hljs.initHighlightingOnLoad();
    //hljs.registerLanguage('mermaid', window.hljsDefineMermaid);
  </script>
  <script src="//jsd.onmicrosoft.cn/npm/highlightjs-line-numbers.js@2.8.0/dist/highlightjs-line-numbers.min.js"></script>
  <script>
    hljs.initLineNumbersOnLoad({
      singleLine: true
    });
  </script>
 <script src="https://jsd.onmicrosoft.cn/npm/mermaid/dist/mermaid.min.js"></script>
   <script>
    mermaid.initialize({
      startOnLoad: true,
      securityLevel: 'loose',
    });
  </script>





  </body>
</html>
